/**
 * @fileoverview   event/handle 添加事件，删除事件，触发事件

 * @date: 12-1-5
 * @time: 上午11:43
 * @author 2kid
 * @version 0.1
 */
/**
 *
 *
 * 属性：

 * 方法：
 * event.add
 * event.del
 */
F.reg('event/handle',function(f,event,dom){
    var win = window,doc = win['document'],docElement = doc.documentElement;
    var ADDEVENT,
        DELEVENT,
        ON,
        __E='__E'+new Date().getTime(),
        _gid=0,
        eventqueue={},
        _w3c='addEventListener' in docElement;
    if(_w3c){
        ADDEVENT='addEventListener';
        DELEVENT='removeEventListener';
        ON='';
    }else{
        ADDEVENT='attachEvent';
        DELEVENT='detachEvent';
        ON='on';
    }


    function execevent(guid,ctx){
        return function(e){

            var equeue=eventqueue[guid];
            var _e=fix(e||window.event);
                for(var i=0;i<equeue['fnqu'].length;i++){
                    if(equeue['fnqu'][i].call(ctx||equeue['ele'],_e)===false){
                        _e.prevent();
                        _e.stop();
                    }
                }
        }

    }

    function addevent(ele,type,fn,ctx){
        var etype=getetype(type);

        var guid=ele[etype] || ++_gid;
        /**
         * eventqueue｛
         *      1：{
         *          ele:ele,
         *          fn:fn,
         *          fnqu:[fn1,fn2]
         *      }
         * ｝
         */
        if(!ele[etype] ){
            ele[etype] = guid;
            eventqueue[guid]={};
            eventqueue[guid]['ele']=ele;
            eventqueue[guid]['fn']=execevent(guid,ctx);
            eventqueue[guid]['fnqu']=[];
        }
        //如果没有定义响应函数，则添加
        if(eventqueue[guid]['fnqu'].length===0){
            ele[ADDEVENT](ON+type,eventqueue[guid]['fn'],false);
        }
        //给当前函数添加标志， 以便删除事件用
        fn['queueid']=eventqueue[guid]['fnqu'].length;

        eventqueue[guid]['fnqu'].push(fn);

    }

    function delevent(ele,type,fn,undefined){
        var etype=getetype(type),
            guid=ele[etype];

        //如果
        if(fn){
            eventqueue[guid]['fnqu'].splice(fn['queueid'],1);
            if(eventqueue[guid]['fnqu'].length===0){
                fn=undefined;
            }
        }
        if(!fn){
            ele[DELEVENT](ON+type,eventqueue[guid]['fn'],false);

            // delete eventqueue[guid] ; ?
            eventqueue[guid]=undefined ;
            ele[etype]=undefined;

        }




    }
    function fireevent(ele,type,ctx){
        var etype=getetype(type),
            guid=ele[etype],
            e = {
                type: type,
                target: ele,
                currentTarget: ele,
                preventDefault: function(){},
                stopPropagation: function(){}
            };
        guid && eventqueue[guid]['fn'].call(ele||ctx,e);
        try {
            ele['on' + type] && ele['on' + type].call(ele);
        } catch (e) {}

    }
    function getetype(type){
        return __E+type;
    }
    function fix(e){
        var _e={},domscroll=dom.docscroll();

        _e.target = e.srcElement;
        _e.relatedTarget = e.toElement || e.fromElement;

        //处理鼠标滚轮
        _e.wheelDelta = -e.detail * 40;

        //获取鼠标相对页面的x位置
        _e.pageX=e.clientX+domscroll.l;
        _e.pageY=e.clientY+domscroll.t;

        //阻止事件默认动作
        _e.prevent = function () {
            _w3c?e.preventDefault():e.returnValue = false;

        };

        //阻止事件传播
        _e.stop= function () {
            _w3c?e.stopPropagation():e.cancelBubble = true;
        };

        //beforeunload 事件时，设置的返回值
        _e.returnval=function(val){
            e.returnValue=val;
        };

        //拷贝默认的
        for (var name in e){
            _e[name] = e[name];
        }
         _e.keyCode= e.charCode  ;

        return _e;

    }



     event=f.merge(event,{
         /**
          * @name F.Event.add
          * @function
          * @namespace 添加事件
          * @param sel 选择器、同dom.query
          * @param type 事件类型 ，鼠标滚轮可直接用  mousewheel
          * @param fn 事件处理函数，在事件处理函数中返回false，会阻止默认动作和事件传播
          * @param ctx
          * @example
          * 例子：
          * 1.
          * event.add('a','click',function(e){
          *     console.log(e)
          *    return false;
          *  });
          */
         add:function(sel,type,fn,ctx){
             f.each(event._getelem(sel),function(ele){
                 addevent(ele,type,fn,ctx);
                 if(type==='mousewheel'){
                     addevent(ele,'DOMMouseScroll',fn,ctx);
                 }
             });
         },
         /**
          *
          * @name F.Event.del
          * @function
          * @namespace 删除事件
          * @param sel 选择器、同dom.query
          * @param type 事件类型 ，鼠标滚轮可直接用  mousewheel
          * @param fn 可选。若传递，则只删除添加的事件处理函数中的当前这个
          * @example
          * 例子：
          * 1.
          * //所有的a元素，添加一次点击事件
          * event.add('a','click',function(e){
          *     event.del('a','click',arguments.callee);
          *     console.log(e)
          *    return false;
          *  });
          */
         del:function(sel,type,fn){
             f.each(event._getelem(sel),function(ele){
                  delevent(ele,type,fn);
                 if(type==='mousewheel'){
                     delevent(ele,'DOMMouseScroll',fn);
                 }

             });
         },
         /**
          * @name F.Event.fire
          * @function
          * @namespace 触发事件，只会触发已添加的事件处理函数、而不不会触发浏览器默认事件动作
          * @param sel
          * @param type
          * @example
          * 例子：
          * 1.
          * event.fire('a','click');
          *
          */
         fire:function(sel,type){
             f.each(event._getelem(sel),function(ele){
                 fireevent(ele,type);

             });

         }
     });





    return event;

},{
    requires:[
        'dom'

    ]
});